from abstract_node.datasheet_parser import EventDataSheetParser
from abstract_node.extended_event import ExtendedNetworkEvent
from auxillaries.periodic_task import PeriodicTask
from abstract_node.output_layer import AbstractOutputLayer
import quantities

class Dispatcher():
    
    def __init__(self,  abstract_node):
        self.abstract_node=abstract_node
        self.periodic_trigger=[]
        if self.abstract_node.channelProperties.period!=0:
            period=float(self.abstract_node.channelProperties.period.magnitude)
            self.periodic_trigger=PeriodicTask(period, 
                                              self.trigger)
        
    def start(self):
        print "dispatcher starts timer"
        if self.periodic_trigger!=[]:
            self.periodic_trigger.startTimer()
        
    def stop(self):
        if self.periodic_trigger!=[]:
            self.periodic_trigger.stopTimer()
            print "Node stoped"
            
    def trigger(self):
        if self.abstract_node.input_layer!=[]:
            self.abstract_node.input_event_access()
            self.abstract_node.input_layer.input_events=[]
        results=self.abstract_node.processing_ctr()
        common_validity=self.abstract_node.evaluation_fct()
        self.abstract_node.output_event_mapping(results, common_validity)
        self.abstract_node.output_layer.transmit(self.abstract_node.output_event)
        self.abstract_node.reset_output_event()                
                   
class AbstractNode():
    
    def __init__(self, eventDataSheet, appName, outputLayer, logger=[]):
    
        self.parser=EventDataSheetParser(filename=eventDataSheet)
        self.channelProperties=self.parser.load_event_datasheet()
        self.appName=appName
        # output Event
        self.output_event=ExtendedNetworkEvent(self.channelProperties)
        
        self.input_layer=[]
        self.input_events=[]                                 # abstrct input event
        self.output_layer=outputLayer                         # Output
        self.dispatcher=Dispatcher(abstract_node=self)        # Dispatcher      

        self.position=[0, 0, 0]*quantities.centimeter
        self.orientation=[0, 0, 0]*quantities.degree
        
    def input_event_mapping(self, value, time=[]):
        pass
      
    def input_event_filtering(self):
        self.input_layer.input_events.append(self.input_layer.input_event)
        return True   
        
    def input_event_access(self):       
        self.input_events=self.input_layer.input_events
    
    def processing_ctr(self):
        results=[]
        return results
    
    def evaluation_fct(self):
        common_validity=1
        return common_validity
    
    def output_event_mapping(self, results, common_validity):
        pass
       
    def reset_output_event(self):
        self.output_event.reset_structure()
        
    def start_node(self):
        self.dispatcher.start()
        
    def stop_node(self):
        self.dispatcher.stop()
        
    def trigger(self):
        self.dispatcher.trigger()
 
    def setPosition(self, position):
        if position.__class__==quantities.quantity.Quantity:
            self.position=position
        else:
            print "Position value have to be equipped with a quantity !!!"
            print "For instance position*quantities.centimeter"
        
    def setOrientation(self, orientation):
        if orientation.__class__==quantities.quantity.Quantity:
            self.orientation=orientation
        else:
            print "Position value have to be equipped with a quantity !!!"
            print "For instance position*quantities.centimeter"  
                
    def getPosition(self):
        return self.position
        
    def getOrientation(self):
        return self.orientation
        
    def __repr__(self):
        output= "\n-----------------------------------------------------\n"
        output+="Application name     %s\n"%self.appName
        output+= "Subject              \"%s\"" %self.channelProperties.subject
        if self.channelProperties.period!=0:
            output+=" (Period %s) \n" %self.channelProperties.period
        else:
            output+=" (Event based publication)\n"
        output+="-----------------------------------------------------\n"
        output+="Channel Datasheet    %s\n" %self.channelProperties.channelDataSheet    
        output+="Format               %s entries\n"%(len(self.channelProperties.eventFormat))
        for entry in self.channelProperties.eventFormat:
            output+="                     {0:12}".format(entry["Name"])
            output+=" - {0:8}".format(entry["DataType"])
            output+=" - {0:2} ".format(entry["Size"])
            if entry["Static"]==True:
                output+="- static\n"
            else:
                output+="- variable\n"
        return output